package cn.elead.chaos.remote.config;

import java.util.concurrent.TimeUnit;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import cn.elead.chaos.framework.properties.ChaosProperties;
import cn.elead.chaos.remote.exception.FeignExceptionResolverService;
import cn.elead.chaos.remote.web.system.service.IRemoteConfigService;
import cn.elead.chaos.remote.web.system.service.IRemoteDeptService;
import cn.elead.chaos.remote.web.system.service.IRemoteDictDataService;
import cn.elead.chaos.remote.web.system.service.IRemoteDictTypeService;
import cn.elead.chaos.remote.web.system.service.IRemoteLoginService;
import cn.elead.chaos.remote.web.system.service.IRemoteMenuService;
import cn.elead.chaos.remote.web.system.service.IRemoteNoticeService;
import cn.elead.chaos.remote.web.system.service.IRemotePostService;
import cn.elead.chaos.remote.web.system.service.IRemoteRoleService;
import cn.elead.chaos.remote.web.system.service.IRemoteShiroService;
import cn.elead.chaos.remote.web.system.service.IRemoteUserService;
import cn.elead.chaos.sso.core.util.SsoUtils;
import feign.Feign;
import feign.Feign.Builder;
import feign.Request;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import feign.Retryer;
import feign.httpclient.ApacheHttpClient;
import feign.jackson.JacksonDecoder;
import feign.jackson.JacksonEncoder;
import lombok.extern.slf4j.Slf4j;

/**
 * https://www.jianshu.com/p/307d47e7d7ab
 * 
 * @author luopeng
 *
 */
@Slf4j
@Configuration
@Component
public class FeignConfiguration {

	@Autowired
	private ChaosProperties chaos;

	/**
	 * 异常处理
	 * 
	 * @return
	 */
	@Bean
	public FeignExceptionResolverService feignExceptionResolverService() {
		return new FeignExceptionResolverService();
	}

	@Bean
	public RequestInterceptor headerInterceptor() {
		return new RequestInterceptor() {
			@Override
			public void apply(RequestTemplate requestTemplate) {
				requestTemplate.header("Content-Type", "application/json");
				requestTemplate.header(chaos.getSso().getXAuthToken(), SsoUtils.getToken());
				requestTemplate.header("tenant", chaos.getSso().getClientId());
			}
		};
	}

	@Bean
	public Builder feignBuilder() {
		Builder feignBuilder = Feign.builder() //
				.requestInterceptor(headerInterceptor()) //
				.client(new ApacheHttpClient()) //
				.encoder(new JacksonEncoder()) //
				.decoder(new JacksonDecoder()) //
				.options(new Request.Options(2000, TimeUnit.MILLISECONDS, 3500, TimeUnit.MILLISECONDS, true)) //
				.retryer(new Retryer.Default(5000, 5000, 3));//
		return feignBuilder;
	}

	@Bean
	public IRemoteUserService remoteUserService() {
		IRemoteUserService remoteUserService = feignBuilder().target(IRemoteUserService.class, chaos.getRemote().getSystembaseUrl());
		if (null != remoteUserService) {
			log.info("feignRemoteUserService 创建成功！");
		} else {
			throw new RuntimeException("feignRemoteUserService 创建失败");
		}
		return remoteUserService;
	}

	@Bean
	public IRemoteDeptService remoteDeptService() {
		IRemoteDeptService remoteDeptService = feignBuilder().target(IRemoteDeptService.class, chaos.getRemote().getSystembaseUrl());
		if (null != remoteDeptService) {
			log.info("feignRemoteDeptService 创建成功！");
		} else {
			throw new RuntimeException("feignRemoteDeptService 创建失败");
		}
		return remoteDeptService;
	}

	@Bean
	public IRemoteMenuService remoteMenuService() {
		IRemoteMenuService remoteMenuService = feignBuilder().target(IRemoteMenuService.class, chaos.getRemote().getSystembaseUrl());
		if (null != remoteMenuService) {
			log.info("feignRemoteMenuService 创建成功！");
		} else {
			throw new RuntimeException("feignRemoteMenuService 创建失败");
		}
		return remoteMenuService;
	}

	@Bean
	public IRemoteRoleService remoteRoleService() {
		IRemoteRoleService remoteRoleService = feignBuilder().target(IRemoteRoleService.class, chaos.getRemote().getSystembaseUrl());
		if (null != remoteRoleService) {
			log.info("feignRemoteRoleService 创建成功！");
		} else {
			throw new RuntimeException("feignRemoteRoleService 创建失败");
		}
		return remoteRoleService;
	}

	@Bean
	public IRemotePostService remotePostService() {
		IRemotePostService remotePostService = feignBuilder().target(IRemotePostService.class, chaos.getRemote().getSystembaseUrl());
		if (null != remotePostService) {
			log.info("feignRemotePostService 创建成功！");
		} else {
			throw new RuntimeException("feignRemotePostService 创建失败");
		}
		return remotePostService;
	}

	@Bean
	public IRemoteConfigService remoteConfigService() {
		IRemoteConfigService remoteConfigService = feignBuilder().target(IRemoteConfigService.class, chaos.getRemote().getSystembaseUrl());
		if (null != remoteConfigService) {
			log.info("feignRemoteConfigService 创建成功！");
		} else {
			throw new RuntimeException("feignRemoteConfigService 创建失败");
		}
		return remoteConfigService;
	}

	@Bean
	public IRemoteDictTypeService remoteDictTypeService() {
		IRemoteDictTypeService remoteDictTypeService = feignBuilder().target(IRemoteDictTypeService.class, chaos.getRemote().getSystembaseUrl());
		if (null != remoteDictTypeService) {
			log.info("feignRemoteDictTypeService 创建成功！");
		} else {
			throw new RuntimeException("feignRemoteDictTypeService 创建失败");
		}
		return remoteDictTypeService;
	}

	@Bean
	public IRemoteDictDataService remoteDictDataService() {
		IRemoteDictDataService remoteDictDataService = feignBuilder().target(IRemoteDictDataService.class, chaos.getRemote().getSystembaseUrl());
		if (null != remoteDictDataService) {
			log.info("feignRemoteDictDataService 创建成功！");
		} else {
			throw new RuntimeException("feignRemoteDictDataService 创建失败");
		}
		return remoteDictDataService;
	}

	@Bean
	public IRemoteNoticeService remoteNoticeService() {
		IRemoteNoticeService remoteNoticeService = feignBuilder().target(IRemoteNoticeService.class, chaos.getRemote().getSystembaseUrl());
		if (null != remoteNoticeService) {
			log.info("feignRemoteNoticeService 创建成功！");
		} else {
			throw new RuntimeException("feignRemoteNoticeService 创建失败");
		}
		return remoteNoticeService;
	}

	@Bean
	public IRemoteLoginService remoteLoginService() {
		IRemoteLoginService remoteLoginService = feignBuilder().target(IRemoteLoginService.class, chaos.getRemote().getSystembaseUrl());
		if (null != remoteLoginService) {
			log.info("feignRemoteLoginService 创建成功！");
		} else {
			throw new RuntimeException("feignRemoteLoginService 创建失败");
		}
		return remoteLoginService;
	}
	
	@Bean
	public IRemoteShiroService remoteShiroService() {
		IRemoteShiroService remoteShiroService = feignBuilder().target(IRemoteShiroService.class, chaos.getRemote().getSystembaseUrl());
		if (null != remoteShiroService) {
			log.info("feignRemoteShiroService 创建成功！");
		} else {
			throw new RuntimeException("feignRemoteShiroService 创建失败");
		}
		return remoteShiroService;
	}
}